package com.qianfeng.smartmeeting.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

@Aspect
@Component
public class LogAspect {

    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    @Pointcut("execution(* com.qianfeng.smartmeeting.service..*(..))")
    public void serviceLog(){};

    @Before("serviceLog()")
    public void doBefore(JoinPoint joinPoint){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            // 记录请求信息
            logger.info("请求URL: {}", request.getRequestURL().toString());
            logger.info("请求方法: {}", request.getMethod());
            logger.info("客户端IP: {}", request.getRemoteAddr());
        }

        // 记录方法调用信息
        logger.info("调用方法: {}.{}",
                joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName());
        logger.info("方法参数: {}", Arrays.toString(joinPoint.getArgs()));

    }

    @After("serviceLog()")
    public void doAfter(JoinPoint joinPoint){
        logger.info("方法执行结束: {}.{}",
                joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName());
    }

    @AfterReturning(returning = "result", pointcut = "serviceLog()")
    public void doAfterReturning(JoinPoint joinPoint, Object result){
        logger.info("方法返回结果: {}.{} -> {}",
                joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName(),
                result);
    }

    @AfterThrowing(throwing = "ex", pointcut = "serviceLog()")
    public void doAfterThrowing(JoinPoint joinPoint, Exception ex) {
        logger.error("方法执行异常: {}.{} -> 异常信息: {}",
                joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName(),
                ex.getMessage(), ex);
    }

    // 环绕通知：可以在方法执行前后做更多操作，如记录执行时间
    @Around("serviceLog()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
        // 执行目标方法
        Object result = pjp.proceed();
        // 计算执行时间
        long time = System.currentTimeMillis() - startTime;
        logger.info("方法执行时间: {}.{} -> {}ms",
                pjp.getSignature().getDeclaringTypeName(),
                pjp.getSignature().getName(),
                time);
        return result;
    }
}
